#include "stdafx.h"
#include "Cashdrawer.h"
using namespace Utility::LoggerLib;
CCashdrawer::CCashdrawer(int nType, int nPort, int nMBType)
: m_nType(nType),
  m_nPort(nPort),
  m_nMBType(nMBType),
  m_nError(0)
{
    m_ComInfo.hCom = NULL;
    m_ComInfo.nParity = 2;
    m_ComInfo.oWrite.hEvent = NULL;
    m_ComInfo.oRead.hEvent = NULL;
}

BOOL CCashdrawer::Initialize()
{
    return TRUE;
}

//////////////////////////////////////////////////////////////////////////
// CComCashdrawer
#include "ComDefinition.h"
CComCashdrawer::CComCashdrawer(int nPort)
: CCashdrawer(EComCashdrawer, nPort)
{
}

CComCashdrawer::~CComCashdrawer()
{
    if (NULL != m_ComInfo.hCom)
    {
        PR_CloseCom(m_ComInfo.hCom, m_ComInfo.oWrite, m_ComInfo.oRead);
    }
}

BOOL CComCashdrawer::Initialize()
{
    CCashdrawer::Initialize();

    m_ComInfo.hCom = PR_OpenCom(m_nPort, m_ComInfo.oWrite, m_ComInfo.oRead, m_ComInfo.nParity, m_nError);
    return NULL == m_ComInfo.hCom ? FALSE : TRUE;
}

#define COMMAND_OPEN_COMCASHDRAWER                               _T("\x1b\x70\x00\x50\x10")
#define COMMAND_OPEN_COMCASHDRAWER_LENGTH                  5*sizeof(TCHAR)
#define COMMAND_GET_COMCASHDRAWER_STATUS                      "\x1d\x72\x02"
#define COMMAND_GET_COMCASHDRAWER_STATUS_LENGTH        3
int CComCashdrawer::Open()
{
    return PR_SendStr2Com(m_ComInfo.hCom, _T("\x1b\x70\x00\x50\x10"), 5*sizeof(TCHAR), m_ComInfo.oWrite) ? 0:-1;
}

int CComCashdrawer::GetStatus()
{
    if (!PR_SendStr2LPT(m_ComInfo.hCom, COMMAND_GET_COMCASHDRAWER_STATUS, COMMAND_GET_COMCASHDRAWER_STATUS_LENGTH, m_ComInfo.oRead))
    {
        return CD_STATUS_UNKNOWN;
    }
    
    TCHAR buf[4];
    memset(buf, '\0', 4*sizeof(TCHAR));
    Sleep(50);
    PR_ReadStrFromCom(m_ComInfo.hCom, buf, 1*sizeof(TCHAR), m_ComInfo.oRead);

    return (buf[0] & 0x01) ? CD_STATUS_CLOSE : CD_STATUS_OPEN;
}

//////////////////////////////////////////////////////////////////////////
// CPTCashdrawer
CPTCashdrawer::CPTCashdrawer(int nPort)
: CCashdrawer(EPrinterwithCashdrawer, nPort)
{
    if (nPort >= COM1 && nPort <= COM6)
    {
        m_ePort = ECOM;
    }
    else if (nPort >= LPT1 && nPort <= LPT3)
    {
        m_ePort = ELPT;
    }
    else if (nPort >= USB1 && nPort <= USB4)
    {
        m_ePort = EUSB;
    }
    else
        m_ePort = EUnkown;

    Log(DEBUG_LEVEL, EPOSChecker, _T("Create PTCashdrawer, and printer port id is %d, port type is %d."), nPort, m_ePort);
}

CPTCashdrawer::~CPTCashdrawer()
{
    if (NULL != m_ComInfo.hCom)
    {
        switch (m_ePort)
        {
        case ECOM:
            PR_CloseCom(m_ComInfo.hCom, m_ComInfo.oWrite, m_ComInfo.oRead);
            break;

        case  ELPT:
            PR_CloseLPT(m_ComInfo.hCom, m_ComInfo.oWrite, m_ComInfo.oRead);
            break;

        case  EUSB:
        default:
            break;    
        }
    }
}

BOOL CPTCashdrawer::Initialize()
{
    CCashdrawer::Initialize();
    switch (m_ePort)
    {
    case ECOM:
        m_ComInfo.hCom = PR_OpenCom(m_nPort, m_ComInfo.oWrite, m_ComInfo.oRead, m_ComInfo.nParity, m_nError);
        Log(DEBUG_LEVEL, EPOSChecker,  _T("Open COM%d."), m_nPort);
        break;
        
    case  ELPT:
        m_ComInfo.hCom = PR_OpenLPT(m_nPort-COM6, m_ComInfo.oWrite, m_ComInfo.oRead, m_nError);
        Log(DEBUG_LEVEL, EPOSChecker, _T("Open LPT%d"), m_nPort - COM6);
        break;

    case  EUSB:
    default:
        return FALSE;
        break;    
    }

    return NULL == m_ComInfo.hCom ? FALSE : TRUE;
}

int CPTCashdrawer::Open()
{
    char buf[32] = "\x1b\x70\x00\x50\x10";
    
    int nRet = -1;
    switch (m_ePort)
    {
    case ECOM:
        nRet = PR_SendStr2Com(m_ComInfo.hCom, buf, 5, m_ComInfo.oWrite);
        break;
    case ELPT:
        nRet = PR_SendStr2LPT(m_ComInfo.hCom, buf, 5, m_ComInfo.oWrite);
        break;
    case EUSB:
    default:
        break;
    }
    Log(DEBUG_LEVEL, EPOSChecker, _T("Open cashdrawer, port id is %d, and return value is %d."), m_nPort, nRet);
    return nRet;
}

int CPTCashdrawer::GetStatus()
{
    char buf[4] = COMMAND_GET_COMCASHDRAWER_STATUS;
    
    switch (m_ePort)
    {
    case ECOM:
        if (!PR_SendStr2Com(m_ComInfo.hCom, COMMAND_GET_COMCASHDRAWER_STATUS, COMMAND_GET_COMCASHDRAWER_STATUS_LENGTH, m_ComInfo.oRead))
        {
            return CD_STATUS_UNKNOWN;
        }
        break;
    case  ELPT:
        if (!PR_SendStr2LPT(m_ComInfo.hCom, COMMAND_GET_COMCASHDRAWER_STATUS, COMMAND_GET_COMCASHDRAWER_STATUS_LENGTH, m_ComInfo.oRead))
        {
            return CD_STATUS_UNKNOWN;
        }
        break;
    case  EUSB:
    default:
        break;
    }

    memset(buf, '\0', 4);
    Sleep(50);
    switch (m_ePort)
    {
    case ECOM:
        PR_ReadStrFromCom(m_ComInfo.hCom, buf, 1, m_ComInfo.oRead);
        break;
    case  ELPT:
        PR_ReadStrFromLPT(m_ComInfo.hCom, buf, 1, m_ComInfo.oRead);
        break;
    case  EUSB:
    default:
        break;
    }
    int nStatus = (buf[0] & 0x01) ? CD_STATUS_CLOSE : CD_STATUS_OPEN;

    Log(DEBUG_LEVEL, EPOSChecker, _T("Get cashdrawer status, port id is %d, and status is %d."), m_nPort, nStatus);
    return nStatus;

}

///////////////////////////////////////////////////////////////////////
// CMBCashdrawer
#include "MyPortTalk.h"
const static int D525_BASE_ADDRESS = 0x1180;

CMBCashdrawer::CMBCashdrawer(int nMBType)
	: CCashdrawer(EMBCashdrawer, EUnkownPort, D525)
{
	m_nStatus = 1;
}

CMBCashdrawer::~CMBCashdrawer()
{
	ClosePortTalk();
}

BOOL CMBCashdrawer::Initialize()
{
	Log(DEBUG_LEVEL, EPOSChecker, _T("Mainboard with cashdrawer initialized."));
	if(IsWinNT())
	{
		Log(DEBUG_LEVEL, EPOSChecker, _T("The platform is WinNT"));
		if(!OpenPortTalk())
		{
			Log(ERROR_LEVEL, EPOSChecker, _T("Failed to open port talk, please check the driver."));
			return FALSE;
		}
		Log(DEBUG_LEVEL, EPOSChecker, _T("Success Open PortTalk!"));
	}
	else
	{
		Log(ERROR_LEVEL, EPOSChecker, _T("The OS is not WinNT, not support now."));
		return FALSE;
	}

	switch(m_nMBType)
	{
	case D525:
		return D525_Initialize();
		break;
	default:
		break;
	}

	return TRUE;
}

int CMBCashdrawer::Open()
{
	/*
		byte by = inportb(BASE_M7062 + 0x0D);

	by = by & 0xBF;
	outportb( BASE_M7062 + 0x0D, by);	//bit6

	Sleep(200);
	by = inportb(BASE_M7062 + 0x0D);
	by = by | 0x40;

	outportb( BASE_M7062 + 0x0D, by);
	*/

	Log(DEBUG_LEVEL, EPOSChecker, _T("Open cashdrawer."));
	BYTE bt = Inp(D525_BASE_ADDRESS + 0x0D);
	bt &= 0xBF;
	Outp(D525_BASE_ADDRESS + 0x0D, bt);
	
	Sleep(200);
	bt = Inp(D525_BASE_ADDRESS + 0x0D);
	bt |= 0x40;

	Outp(D525_BASE_ADDRESS + 0x0D, bt);

	return 0;
}

int CMBCashdrawer::GetStatus()
{
	/*
	byte by = inportb(BASE_M7062 + 0x0D);   //bit 5
	if( by & 0x20 )
		iRes = 1;
	else iRes = 0;
	return iRes;
	*/
	BYTE bt = Inp(D525_BASE_ADDRESS + 0x0D);;

	if(bt & 0x20)
	{
		m_nStatus = 1;
	}
	else
	{
		m_nStatus = 0;
	}
	Log(DEBUG_LEVEL, EPOSChecker, _T("Get Cashdrawer status : %d."), m_nStatus);
	return m_nStatus;
}

BOOL CMBCashdrawer::D525_Initialize()
{
	/*
	byte by = inportb(BASE_M7062 + 0x01);

	by = by | 0x60;				//bit5,bit6
	outportb( BASE_M7062 + 0x01, by);

	by = inportb(BASE_M7062 + 0x05);

	by = by | 0x20;  //bit 5 input
	by = by & 0xBF;  //bit 6 output  

	outportb( BASE_M7062 + 0x05, by);
	*/
	

	Log(DEBUG_LEVEL, EPOSChecker, _T("D525 initializ start."));
	UCHAR  bt = Inp(D525_BASE_ADDRESS + 0x01);
	bt |= 0x60;
	Outp(D525_BASE_ADDRESS + 0x01, bt);
	bt = Inp(D525_BASE_ADDRESS + 0x05);
	bt |= 0x20;
	bt &= 0xBF;

	Outp(D525_BASE_ADDRESS + 0x05, bt);
	Log(DEBUG_LEVEL, EPOSChecker, _T("D525 initialized."));

	return TRUE;
}
